const cloud = require('wx-server-sdk')
const axios = require('axios')
const crypto = require('crypto')
cloud.init()

// 从环境变量读取配置（需在小程序云开发控制台设置）
const APP_ID = "2025016182"  
const APP_KEY = "cEwtzUOvZOobhvaM" 

/**
 * 生成签名（关键修正：包含请求体）
 * @param {string} method 请求方法（如 POST）
 * @param {string} uri API 路径（如 /vivogpt/completions）
 * @param {object} params 查询参数（如 { requestId: xxx }）
 * @param {object} data 请求体数据（如 { prompt: xxx, model: xxx }）
 * @returns {object} 包含签名、时间戳、随机数的对象
 */
function generateSignature(method, uri, params, headersData) { // 传入头部数据（app-id/timestamp/nonce）
  const timestamp = headersData.timestamp; // 从头部数据获取 timestamp（不再从查询参数获取）
  const nonce = headersData.nonce; // 从头部数据获取 nonce

  // 1. 处理查询参数（仅 requestId，按官方示例无 timestamp）
  const queryStr = `requestId=${encodeURIComponent(params.requestId)}`; // 仅包含 requestId

  // 2. 构建头部键值对（每个头部占一行）
  const headerLines = [
    `x-ai-gateway-app-id:${headersData.appId}`,
    `x-ai-gateway-timestamp:${timestamp}`,
    `x-ai-gateway-nonce:${nonce}`
  ].join('\n');

  // 3. 拼接签名字符串（共 7 部分，无请求体）
  const stringToSign = [
    method.toUpperCase(),
    uri,
    queryStr,
    headersData.appId,
    timestamp, // 单独一行，非查询参数
    headerLines // 头部键值对，每行一个
  ].join('\n');
  console.log("signing_string是"+stringToSign);
  // 4. 计算签名（Base64 编码）
  const hmac = crypto.createHmac('sha256', APP_KEY);
  const hexDigest = hmac.update(stringToSign).digest('hex'); // 十六进制字符串
  // 2. 将十六进制字符串转换为 Buffer（原始二进制数据）
  const hexBuffer = Buffer.from(hexDigest, 'hex');
  // 3. 对二进制数据进行 Base64 编码，得到最终签名
  const signature = hexBuffer.toString('base64');
  console.log("签名是"+signature);
  return { signature, timestamp, nonce };
}
function generate8BitNonce() {
  // 字符集：大小写字母 + 数字（共 62 个字符）
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  const bytes = crypto.randomBytes(8); // 生成 8 字节随机数（确保每个字符随机）
  let nonce = '';
  for (const byte of bytes) {
    // 每个字节映射到 0-61 范围（chars 的索引）
    nonce += chars[byte % chars.length];
  }
  return nonce;
}

exports.main = async (event) => {
  console.log("ID是"+APP_ID);
  console.log("key是"+APP_KEY);
  try {
    const { prompt = '写一首春天的诗' } = event  // 支持前端传入 prompt，默认值
    const requestId = crypto.randomUUID()
    const sessionId = crypto.randomUUID()
    const uri = '/vivogpt/completions'
    const method = 'POST'
    const nonce = generate8BitNonce();

    // 1. 构造查询参数（仅包含 requestId，vivo 文档要求的必传参数）
    const timestamp = Math.floor(Date.now() / 1000);
    const params = { requestId}
    // 头部数据（用于签名和请求头）
    const headersData = {
      appId: APP_ID,
      timestamp: timestamp.toString(),
      nonce: nonce
    };
    // 2. 构造请求体（包含业务参数）
    const data = {
      prompt,
      model: 'vivo-BlueLM-TB-Pro',
      sessionId
    }

    // 3. 生成签名（传入请求体 data）
    const { signature } = generateSignature('POST', '/vivogpt/completions', params, headersData);

    // 4. 构建请求头（新增关键头部 X-AI-GATEWAY-SIGNED-HEADERS）
    const headers = {
      'Content-Type': 'application/json',
      'X-AI-GATEWAY-APP-ID': APP_ID,
      'X-AI-GATEWAY-TIMESTAMP': timestamp,
      'X-AI-GATEWAY-NONCE': nonce,
      'X-AI-GATEWAY-SIGNED-HEADERS': 'x-ai-gateway-app-id;x-ai-gateway-timestamp;x-ai-gateway-nonce', // 声明参与签名的头部
      'X-AI-GATEWAY-SIGNATURE': signature
    }

    // 5. 发送请求（使用 HTTPS，确保 URL 正确）
    const response = await axios.post(
      `https://api-ai.vivo.com.cn/vivogpt/completions?requestId=${requestId}`,
      data,
      { headers }
    );

    // 6. 处理响应（按 vivo 文档格式解析）
    if (response.data.code === 0) {
      // return {
      //   code: 0,
      //   message: 'success',
      //   data: response.data.data.content,  // vivo 返回的内容字段
      //   requestId,
      //   sessionId
      // }
      return response.data.data.content;
    } else {
      console.error('vivo API 错误:', response.data.msg)
      return {
        code: response.data.code,
        errMsg: response.data.msg
      }
    }

  } catch (error) {
    console.error('请求失败:', error.message)
    return {
      code: error.response?.status || 500,
      errMsg: error.response?.data?.msg || error.message
    }
  }
}